#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
import inspect


class BaseLibraryInit(object):
    """
    获取公共库的keyword
    """

    def __init__(self, library, path):
        self.path = path
        self.modules = []

    def _getattr(self):
        pass

    def get_keywords(self):
        cls = self.get_all_modules()
        k = []
        for key, value in cls.items():
            sys.path.append(key)
            cl = __import__(value)
            c = inspect.getmembers(cl)
            for name in dir(c):
                if hasattr(getattr(c, name), 'robot_name'):
                    k.append(name)
        return k

    def get_all_modules(self):
        self.get_path()
        module = []
        print(len(self.modules))
        for mm in self.modules:
            if 'interface' in mm:
                module.append(mm)
        cls = {}
        for m in module:
            module = m.rsplit('\\', 1)[1].split('.')[0]
            module_path = m.rsplit('\\', 1)[0]
            if not module.startswith('__'):
                cls[module_path] = module
        return cls

    file_path = None

    def get_path(self):
        if self.file_path:
            p = self.file_path
        else:
            p = self.path
        for d in os.listdir(p):
            self.file_path = os.path.join(p, d)
            if os.path.isdir(self.file_path):
                self.get_path()
            else:
                self.modules.append(self.file_path)

    def get_method_obj_from_cls_obj(self, cls_obj, method_name):
        """
        返回测试方法对象
        :param cls_obj:
        :param method_name:
        :return:
        """
        return getattr(cls_obj, method_name)

    def get_args_from_method_obj(self, method_obj):
        """
        返回测试方法的参数和
        :param method_obj:
        :return:
        """
        return method_obj.__code__.co_varnames, method_obj.__code__.co_argcount - 1


class UserKeywordsInit(object):
    """
    用户自定义关键字
    """
    _module_suffix = 'library.py'
    _cls_suffix = 'Library'
    _method_suffix = 'user'

    def __init__(self):
        self.data = []

    def get_module_obj(self, module_path):
        """
        :param module_path: 包名
        :return:
        """
        package = self.get_module_name(module_path)
        print('package :{}'.format(package))
        if os.path.dirname(module_path) not in sys.path:
            sys.path.append(os.path.dirname(module_path))
        return __import__(package, fromlist=True)

    def get_module_name(self, module_path):
        """
        返回模块名称
        :param module_path:
        :return:
        """
        if os.path.isfile(module_path):
            return inspect.getmodulename(module_path)
        else:
            raise FileExistsError('{} is not file'.format(module_path))

    def is_child(self, obj, cls):
        """
        判断obj是否继承cls
        :param obj:
        :param cls: 目标类
        :return:
        """
        try:
            for i in obj.__bases__:
                if i is cls or isinstance(i, cls):
                    return True
            for i in obj.__bases__:
                if self.is_child(i, cls):
                    return True
        except AttributeError:
            return self.is_child(obj.__class__, cls)
        return False

    def get_cls_name_from_module(self, module_path):
        """
        返回模块下以“Test”结尾的类的名称
        :param module_path:
        :return:
        """
        cls_name = []
        module_obj = self.get_module_obj(module_path)
        print(module_obj)
        for m in dir(module_obj):
            if m.endswith(self._cls_suffix):
                cls_name.append(m)
        print(cls_name)
        return cls_name

    def get_cls_obj_from_module(self, cls_name, module_path):
        """
        返回
        :param cls_name:
        :return:
        """
        module_obj = self.get_module_obj(module_path)
        if hasattr(module_obj, cls_name):
            return getattr(module_obj, cls_name)()
        else:
            raise TypeError('{} is not expect type:object'.format(module_obj))

    def get_method_name_from_cls_obj(self, cls_obj):
        """
        返回类的测试方法的列表
        :param cls_obj:
        :return:
        """
        method_names = []
        for m in dir(cls_obj):
            if m.startswith(self._method_suffix):
                method_names.append(m)
        print("method_name {}".format(method_names))
        return method_names

    def get_method_obj_from_cls_obj(self, cls_obj, method_name):
        """
        返回测试方法对象
        :param cls_obj:
        :param method_name:
        :return:
        """
        return getattr(cls_obj, method_name)

    def get_args_from_method_obj(self, method_obj):
        """
        返回测试方法的参数和
        :param method_obj:
        :return:
        """
        return method_obj.__code__.co_varnames, method_obj.__code__.co_argcount - 1

    def get_all_test_from_module(self, module_path):
        cls_data = []
        module_data = {}
        module_data['module_name'] = self.get_module_name(module_path)
        module_data['module_path'] = module_path
        module_data['cls_detail'] = cls_data
        for c in self.get_cls_name_from_module(module_path):
            cls_dict = {}
            method_data = []
            cls_dict["cls_name"] = c
            cls_obj = self.get_cls_obj_from_module(c, module_path)
            for m in self.get_method_name_from_cls_obj(cls_obj):
                method_dict = {}
                method_obj = self.get_method_obj_from_cls_obj(cls_obj, m)
                method_dict["method_name"] = m
                method_dict["args_count"] = self.get_args_from_method_obj(method_obj)[1]
                method_dict["args_names"] = self.get_args_from_method_obj(method_obj)[0][1:]
                method_data.append(method_dict)
            cls_dict["method_detail"] = method_data
            cls_data.append(cls_dict)
        # print(cls_data)
        return module_data

    def get_all_test_modules_path(self, path):
        if len(os.listdir(path)):
            for d in os.listdir(path):
                tmp_path = os.path.join(path, d)
                if os.path.isfile(tmp_path) and tmp_path.endswith(self._module_suffix):
                    print(tmp_path)
                    self.data.append(self.get_all_test_from_module(tmp_path))
                elif os.path.isdir(tmp_path):
                    self.get_all_test_modules_path(tmp_path)

    def get_data(self):
        return self.data


def func(a, b):
    """
    :param a:
    :param b:
    :return:
    """
    d = {
        'a': 'a',
        'b': 'b'
        }
    return d


if __name__ == '__main__':
    # u = UserKeywordsInit()
    # data = u.get_all_test_from_module(module_path='request_library.py')
    # print(data)
    print(dir(func))
    # setattr(func, 'return_val', d)
    print(func.__getattribute__('d'))
